home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 2 / Gold Medal Software Volume 2 (Gold Medal) (1994).iso / archive / lsize24.arj / LSIZE.C next >
C/C++ Source or Header  |  1994-01-07  |  25KB  |  679 lines

  1. #include <stdio.h>
  2. #include <conio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <dir.h>
  6. #define BUF_SIZ 20000
  7. #define MAX_SUB_FILES 4000
  8. #define demand(fact, remark) {\
  9.     if (!(fact)) {\
  10.         fprintf(stderr, "\nError ->  " #fact "\n");\
  11.         fprintf(stderr, #remark "\n");\
  12.         perror("error");\
  13.         fcloseall();\
  14.         _setcursortype(_NORMALCURSOR);\
  15.         abort();\
  16.         exit(1);\
  17.     }\
  18. }
  19. /************************** Variables *************************************/
  20. typedef struct{                 /* Structure to hold file info */
  21.     unsigned long int position;  /* location of file in LZH from beginning */
  22.     char filenum;                /* subfile number file will be written to */
  23.     unsigned long int size;      /* file size */
  24.     char *name;                  /* file name - allocated dynamically */
  25.     unsigned long int size2;
  26.     unsigned long int position2;
  27.     } record;
  28. record *file[MAX_SUB_FILES];    /* array of pointers to file records */
  29. unsigned long int fsize;        /* used to hold various file sizes    */
  30. unsigned long int nsize[256];   /* subfile lengths */
  31. unsigned long int i;            /* iteration variable */
  32. unsigned long int skip;         /* used to hold skip file length     */
  33. unsigned long int ovrwrt;       /* overwrite flag(0=dont ovrwrt)     */
  34. unsigned long int tsize;        /* target file size(max for subfiles */
  35. unsigned long int bcount;       /* byte count: used for file buffer  */
  36. unsigned int position;
  37. unsigned int skipper;
  38. unsigned int fsize2;
  39. unsigned int rotaten;
  40. char flag;
  41. unsigned long int startdir=0;
  42. unsigned long int dirsize=0;
  43. char *strptr;
  44. unsigned char subfile;          /* subfile number */
  45. unsigned char max;              /* max = total number of subfiles    */
  46. int count;                      /* count = number of files in archive    */
  47. int count2;
  48. int str_len;
  49. unsigned long int total_size;   /* accumulator -total size of a subfile */
  50. unsigned int hsize;             /* header size */
  51. int j,k;                        /* loop counters */
  52. char temp[MAXPATH];             /* temp string storage */
  53. char prefix[MAXPATH];           /* prefix for target files */
  54. char suffix[4];                 /* holds subfile number suffix 1,2,3,...*/
  55. char ifile[MAXPATH];            /* name of source file */
  56. char tfile[MAXPATH];            /* temp storage for manip file names*/
  57. char buffer[BUF_SIZ];           /* buffer for reading and writing files */
  58. char ans;                       /* answer for: Overwrite file?          */
  59. char drive[MAXDRIVE];
  60. char dir[MAXDIR];
  61. char comment[85];
  62. char iname[MAXFILE];
  63. char oname[MAXFILE];
  64. char ext[MAXEXT];
  65. char saveext[MAXEXT];
  66. int flags;
  67. FILE *fp,*sfp;
  68. void sortfs(void);
  69. void help(void);
  70. /********* MAIN PROGRAM **********/
  71. void main(int argc, char *argv[]) /** argc = number of command line args ***/
  72. {                              /**** argv = array containing actual args **/
  73. int lastarg=argc-1;
  74. if(argc<3) help();
  75. if(strtol(argv[lastarg],NULL,10)<0)
  76.     { puts("Error: Invalid file size"); exit(1);}
  77. if(!strcmp(argv[lastarg],"1.44M") || !strcmp(argv[lastarg],"1.44m")\
  78. || !strcmp(argv[lastarg],"1.4M")|| !strcmp(argv[lastarg],"1.4m")) tsize=1457664;
  79. else if(!strcmp(argv[lastarg],"720K") || !strcmp(argv[lastarg],"720k")) tsize=730112;
  80. else if(!strcmp(argv[lastarg],"1.2M") || !strcmp(argv[lastarg],"1.2m")) tsize=1457664;
  81. else if(!strcmp(argv[lastarg],"360K") || !strcmp(argv[lastarg],"360k")) tsize=362496;
  82. else tsize=strtoul(argv[lastarg],NULL,10);
  83. strcpy(ifile,argv[1]);
  84. flags=fnsplit(ifile,drive,dir,iname,ext);
  85. if(!(flags & EXTENSION)){        /* If no extension on source file */
  86.     strcpy(tfile,ifile);
  87.     strcat(tfile, ".LZH");                       // try LZH
  88.     fp=fopen(tfile, "rb");
  89.     if(!fp){
  90.         strcpy(tfile,ifile);
  91.         strcat(tfile, ".ARJ");                    // try ARJ
  92.         fp=fopen(tfile, "rb");
  93.         }
  94.     if(!fp){
  95.         strcpy(tfile,ifile);                      // try ZIP
  96.         strcat(tfile, ".ZIP");
  97.         fp=fopen(tfile, "rb");
  98.         }
  99.     strcpy(ifile, tfile);
  100.     fclose(fp);
  101.     }
  102. fp=fopen(ifile, "rb");                                // Open source file
  103. demand(fp!=NULL, Could not open source file);
  104. strupr(ifile);                                  // conv to upper case
  105. flags=fnsplit(ifile,drive,dir,iname,ext);
  106. strcpy(saveext, ext);                          // save file name extension
  107. /********************************* Search LZH file ************************/
  108. printf("\n...searching file %s\n",ifile);
  109. skip=0;
  110. count=0;
  111. if(!strcmp(ext,".LZH")) {
  112. while(!feof(fp)){
  113.     demand(count<MAX_SUB_FILES, Sorry - Too many files in LZH);
  114.     file[count]=malloc(sizeof(record));
  115.     demand(file[count]!=NULL, Out of memory);
  116.     file[count]->position=skip;
  117.     hsize=fgetc(fp);
  118.     demand(!ferror(fp),Read error);
  119.     if(hsize==0) break;
  120.     if(feof(fp)) break;
  121.     fgetc(fp);
  122.     if(feof(fp)) break;
  123.     fgets(temp,6,fp);
  124.     demand(!strncmp(temp,"-lh",3),LZH file has problems);
  125.     fread(&fsize,sizeof(long),1,fp);
  126.     file[count]->size=fsize+hsize+2;
  127.     file[count]->filenum=0;
  128.     skip+=file[count]->size;
  129.     fseek(fp, (long)10, SEEK_CUR);
  130.     fgets(temp,fgetc(fp)+1,fp);
  131.     file[count]->name = malloc(strlen(temp)+1);
  132.     demand(file[count]->name!=NULL, Out of memory!);
  133.     strcpy(file[count]->name, temp);
  134.     count++;
  135.     fseek(fp, fsize+5, SEEK_CUR);
  136.  }
  137. }
  138. /*********************** SEARCH ARJ FILE **********************************
  139.       ARJ archives contains two types of header blocks:
  140.  
  141.     Archive main header - This is located at the head of the archive
  142.     Local file header   - This is located before each archived file
  143.  
  144.       Structure of main header (low order byte first):
  145.  
  146.       Bytes Description
  147.       ----- -------------------------------------------------------------------
  148.          2   header id (main and local file) = 0x60 0xEA
  149.          2   basic header size (from 'first_hdr_size' thru 'comment' below)
  150.          = first_hdr_size + strlen(filename) + 1 + strlen(comment) + 1
  151.          = 0 if end of archive
  152.          maximum header size is 2600
  153.  
  154.          1   first_hdr_size (size up to and including 'extra data')
  155.          1   archiver version number
  156.          1   minimum archiver version to extract
  157.          1   host OS   (0 = MSDOS, 1 = PRIMOS, 2 = UNIX, 3 = AMIGA, 4 = MAC-OS)
  158.               (5 = OS/2, 6 = APPLE GS, 7 = ATARI ST, 8 = NEXT)
  159.               (9 = VAX VMS)
  160.          1   arj flags
  161.               (0x01 = NOT USED)
  162.               (0x02 = OLD_SECURED_FLAG)
  163.               (0x04 = VOLUME_FLAG)  indicates presence of succeeding
  164.                         volume
  165.               (0x08 = NOT USED)
  166.               (0x10 = PATHSYM_FLAG) indicates archive name translated
  167.                         ("\" changed to "/")
  168.               (0x20 = BACKUP_FLAG) indicates backup type archive
  169.               (0x40 = SECURED_FLAG)
  170.          1   security version (2 = current)
  171.          1   file type        (must equal 2)
  172.          1   reserved
  173.          4   date time when original archive was created
  174.          4   date time when archive was last modified
  175.          4   archive size (currently used only for secured archives)
  176.          4   security envelope file position
  177.          2   filespec position in filename
  178.          2   length in bytes of security envelope data
  179.          2   (currently not used)
  180.          ?   (currently none)
  181.  
  182.          ?   filename of archive when created (null-terminated string)
  183.          ?   archive comment  (null-terminated string)
  184.  
  185.          4   basic header CRC
  186.  
  187.          2   1st extended header size (0 if none)
  188.          ?   1st extended header (currently not used)
  189.          4   1st extended header's CRC (not present when 0 extended header size)
  190.  
  191.  
  192.       Structure of local file header (low order byte first):
  193.  
  194.       Bytes Description
  195.       ----- -------------------------------------------------------------------
  196.          2   header id (main and local file) = 0x60 0xEA
  197.          2   basic header size (from 'first_hdr_size' thru 'comment' below)
  198.          = first_hdr_size + strlen(filename) + 1 + strlen(comment) + 1
  199.          = 0 if end of archive
  200.          maximum header size is 2600
  201.  
  202.          1   first_hdr_size (size up to and including 'extra data')
  203.          1   archiver version number
  204.          1   minimum archiver version to extract
  205.          1   host OS   (0 = MSDOS, 1 = PRIMOS, 2 = UNIX, 3 = AMIGA, 4 = MAC-OS)
  206.               (5 = OS/2, 6 = APPLE GS, 7 = ATARI ST, 8 = NEXT)
  207.               (9 = VAX VMS)
  208.          1   arj flags (0x01 = GARBLED_FLAG) indicates passworded file
  209.               (0x02 = NOT USED)
  210.               (0x04 = VOLUME_FLAG)  indicates continued file to next
  211.                         volume (file is split)
  212.               (0x08 = EXTFILE_FLAG) indicates file starting position
  213.                         field (for split files)
  214.               (0x10 = PATHSYM_FLAG) indicates filename translated
  215.                         ("\" changed to "/")
  216.               (0x20 = BACKUP_FLAG)  indicates file marked as backup
  217.          1   method    (0 = stored, 1 = compressed most ... 4 compressed fastest)
  218.          1   file type (0 = binary,    1 = 7-bit text)
  219.               (3 = directory, 4 = volume label)
  220.          1   reserved
  221.          4   date time modified
  222.          4   compressed size
  223.          4   original size (this will be different for text mode compression)
  224.          4   original file's CRC
  225.          2   filespec position in filename
  226.          2   file access mode
  227.          2   host data (currently not used)
  228.          ?   extra data
  229.         4 bytes for extended file starting position when used
  230.         (these bytes are present when EXTFILE_FLAG is set).
  231.         0 bytes otherwise.
  232.  
  233.          ?   filename (null-terminated string)
  234.          ?   comment  (null-terminated string)
  235.  
  236.          4   basic header CRC
  237.  
  238.          2   1st extended header size (0 if none)
  239.          ?   1st extended header (currently not used)
  240.          4   1st extended header's CRC (not present when 0 extended header size)
  241.  
  242.          ...
  243.  
  244.          ?   compressed file
  245. ****************************************************************************/
  246. if(!strcmp(ext,".ARJ")) {                             /* skip main header */
  247.     file[count]=malloc(sizeof(record));
  248.     file[count]->name = malloc(100);
  249.     demand(file[count]->name!=NULL, Out of memory!);
  250.     demand(file[count]!=NULL, Out of memory);
  251.     file[count]->position=skip;                       /* save file position */
  252.     file[count]->filenum=1;
  253.     strcpy(file[count]->name,"HEADER");
  254.     fread(&hsize,sizeof(int),1,fp);
  255.     demand(hsize==0xEA60, ARJ main header file is corrupt);
  256.     fread(&hsize,sizeof(long),1,fp);
  257.     fseek(fp, (long)hsize+2, SEEK_CUR);
  258.     fread(&position, sizeof(int),1,fp);    /* read file position(skip path) */
  259.     fseek(fp, (long)position, SEEK_CUR);
  260.     skip=hsize+10+position;
  261.     file[count++]->size=skip;
  262. while(!feof(fp)){                                    /*** get files ***/
  263.     demand(count<MAX_SUB_FILES, Sorry - Too many files in ARJ);
  264.     file[count]=malloc(sizeof(record));
  265.     demand(file[count]!=NULL, out of memory);
  266.     file[count]->position=skip;                       /* save file position */
  267.     fread(&hsize,sizeof(int),1,fp);
  268.     demand(hsize==0xEA60, ARJ local hdr file is corrupt);  /* verify header info */
  269.     fread(&skipper,sizeof(int),1,fp);                       /* get header size */
  270.     skip+=skipper+4;
  271.     file[count]->size=skipper+4;
  272.     hsize=(long)fgetc(fp);                       /* get 1st header size */
  273.     demand(!ferror(fp), read error);
  274.     if(hsize==0) break;
  275.     if(feof(fp)) break;
  276.     fseek(fp,(long)11, SEEK_CUR);
  277.     fread(&fsize,sizeof(long),1,fp);         /* read compressed file size */
  278.     file[count]->filenum=0;
  279.     fseek(fp, (long)8, SEEK_CUR);
  280.     fread(&position, sizeof(int),1,fp);    /* read file position(skip path) */
  281.     fseek(fp, (long)hsize-26+position, SEEK_CUR);
  282.     //strptr=(char *)&(file[count]->name);
  283.     strptr = temp;
  284.     do
  285.         *strptr =fgetc(fp);
  286.     while(*strptr++!=0);
  287.     file[count]->name = malloc(strlen(temp)+1);
  288.     demand(file[count]->name!=NULL, out of memory!);
  289.     strcpy(file[count]->name, temp);
  290.     while(fgetc(fp)!=0);
  291.     fseek(fp, (long)4, SEEK_CUR);
  292.     fread(&position,sizeof(int),1,fp);
  293.     file[count]->size+=fsize+6+position;
  294.     skip+=fsize+6+position;
  295.     count++;
  296.     fseek(fp, fsize+position, SEEK_CUR);
  297.  }
  298. total_size=0;
  299. }
  300. /*********************** SEARCH ZIP FILE ***********************************
  301. General Format of a ZIP file
  302. ----------------------------
  303.  
  304.   Files stored in arbitrary order.
  305.  
  306.   Overall zipfile format:
  307.  
  308.      [local file header + file data + data_descriptor] . . .
  309.      [central directory] end of central directory record
  310.  
  311.  
  312.   A.  Local file header:
  313.  
  314.     local file header signature     4 bytes  (0x04034b50)
  315.     version needed to extract       2 bytes
  316.     general purpose bit flag        2 bytes
  317.     compression method              2 bytes
  318.     last mod file time              2 bytes
  319.     last mod file date              2 bytes
  320.     crc-32                          4 bytes
  321.     compressed size                 4 bytes
  322.     uncompressed size               4 bytes
  323.     filename length                 2 bytes
  324.     extra field length              2 bytes
  325.  
  326.     filename (variable size)
  327.     extra field (variable size)
  328.  
  329.  
  330.   B.  Data descriptor:
  331.  
  332.     crc-32                          4 bytes
  333.     compressed size                 4 bytes
  334.     uncompressed size               4 bytes
  335.  
  336.         This descriptor exists only if bit 3 of the general
  337.         purpose bit flag is set (see below).  It is byte aligned
  338.         and immediately follows the last byte of compressed data.
  339.         This descriptor is used only when it was not possible to
  340.         seek in the output zip file, e.g., when the output zip file
  341.         was standard output or a non seekable device.
  342.  
  343.   C.  Central directory structure:
  344.  
  345.         [file header] . . .  end of central dir record
  346.  
  347.         File header:
  348.  
  349.     central file header signature   4 bytes  (0x02014b50)
  350.     version made by                 2 bytes
  351.     version needed to extract       2 bytes
  352.     general purpose bit flag        2 bytes
  353.     compression method              2 bytes
  354.     last mod file time              2 bytes
  355.     last mod file date              2 bytes
  356.     crc-32                          4 bytes
  357.     compressed size                 4 bytes
  358.     uncompressed size               4 bytes
  359.     filename length                 2 bytes
  360.     extra field length              2 bytes
  361.     file comment length             2 bytes
  362.     disk number start               2 bytes
  363.     internal file attributes        2 bytes
  364.     external file attributes        4 bytes
  365.     relative offset of local header 4 bytes
  366.  
  367.     filename (variable size)
  368.     extra field (variable size)
  369.     file comment (variable size)
  370.  
  371.         End of central dir record:
  372.  
  373.     end of central dir signature    4 bytes  (0x06054b50)
  374.     number of this disk             2 bytes
  375.     number of the disk with the
  376.     start of the central directory  2 bytes
  377.     total number of entries in
  378.     the central dir on this disk    2 bytes
  379.     total number of entries in
  380.     the central dir                 2 bytes
  381.     size of the central directory   4 bytes
  382.     offset of start of central
  383.     directory with respect to
  384.     the starting disk number        4 bytes
  385.     zipfile comment length          2 bytes
  386.     zipfile comment (variable size)
  387. ****************************************************************************/
  388.  
  389. if(!strcmp(ext,".ZIP")) {                             /* skip main header */
  390.  
  391. while(!feof(fp)){                                    /*** get files ***/
  392.     fread(&fsize,sizeof(long),1,fp);
  393.     if(fsize==0x04034b50)   /* verify header info LOCAL*/
  394.     {
  395.         demand(count<MAX_SUB_FILES, Sorry - Too many files in ZIP);
  396.         file[count]=malloc(sizeof(record));
  397.         demand(file[count]!=NULL, out of memory);
  398.         file[count]->position=skip;                       /* save file position */
  399.         fseek(fp, (long)14, SEEK_CUR);
  400.         fread(&fsize,sizeof(long),1,fp);                  /* get file size */
  401.         file[count]->size=fsize;
  402.         fseek(fp, (long)4, SEEK_CUR);
  403.         fread(&skipper,sizeof(int),1,fp);            /* get file name len */
  404.         fread(&hsize,sizeof(int),1,fp);             /* get extra len */
  405.         file[count]->size+=hsize;
  406.         if(feof(fp)) break;
  407.         file[count]->name = malloc(skipper+1);
  408.         demand(file[count]->name!=NULL, out of memory!);
  409.         fgets(file[count]->name,skipper+1,fp);       /* get file name len */
  410.         fseek(fp,file[count]->size, SEEK_CUR);
  411.         file[count]->size+=skipper+30;
  412.         skip+=file[count]->size;
  413.         file[count]->filenum=0;
  414.         count++;
  415.         }
  416. else if(fsize==0x02014b50)   /* verify header info CENTRALDIR*/
  417.     {
  418.         file[count2]->position2=skip;              /* save file position */
  419.         fseek(fp, (long)24, SEEK_CUR);
  420.         fread(&fsize2,sizeof(int),1,fp);                  /* get file name size */
  421.         if(feof(fp)) break;
  422.         fread(&skipper,sizeof(int),1,fp);            /* get extra len */
  423.         if(feof(fp)) break;
  424.         fread(&hsize,sizeof(int),1,fp);             /* get comment len */
  425.         if(feof(fp)) break;
  426.         fseek(fp,(long)8, SEEK_CUR);
  427.         fread(&startdir,sizeof(long),1,fp);             /* get position */
  428.         while(file[rotaten]->position!=startdir)
  429.             rotaten = (rotaten+1) % count;
  430.         file[rotaten]->size2=hsize+skipper+fsize2+46;
  431.         file[rotaten]->size+=file[rotaten]->size2;
  432.         fseek(fp, (long)fsize2+skipper+hsize, SEEK_CUR);
  433.  
  434.         if(feof(fp)) break;
  435.         skip+=file[rotaten]->size2;
  436.         count2++;
  437.         }
  438. else if(fsize==0x06054b50)   /* verify header info ENDOFCENTRALDIR*/
  439.     {
  440.         fsize=skip;                                  /* save file position */
  441.         demand(count==count2, ZIP file is damaged);
  442.         fseek(fp, (long)16, SEEK_CUR);
  443.         fread(&fsize2,sizeof(int),1,fp);                  /* get file name size */
  444.         if(feof(fp)) break;
  445.         fseek(fp, (long)fsize2, SEEK_CUR);
  446.         break;
  447.         }
  448. else demand(1==0, ZIP file is damaged);
  449.  }
  450. }
  451. fclose(fp);
  452. if(count<2) {
  453.     printf("%s only contains one file!\n",ifile);
  454.     puts("File cannot be sized!  Use a physical file splitting utility");
  455.     exit(1);
  456.     }
  457. sortfs();   /*** Sort file names by size ***/
  458. printf("...sizing to %lu bytes\n",tsize);
  459.   if(!strcmp(saveext,".LZH") && tsize<=file[0]->size) {
  460.     printf("Error: Impossible to size archive to %lu bytes.\n",tsize);
  461.     printf("%s contains a file, %s, that is %lu bytes compressed.\n",ifile\
  462.     ,file[0]->name,file[0]->size);
  463.     printf("Target file size must be at least %lu bytes to accomodate this file.\n"\
  464.     ,file[0]->size+1);
  465.     printf("If you require a %lu byte file size use a physical file splitting utility\n",tsize);
  466.   exit(1);
  467.   }
  468. if(!strcmp(saveext,".ARJ") && tsize < file[0]->size+4+file[1]->size) {
  469.     printf("Error: Impossible to size archive to %lu bytes.\n",tsize);
  470.     printf("%s contains a file, %s, that is %lu bytes compressed.\n",ifile\
  471.     ,file[1]->name,file[1]->size);
  472.     printf("Target file size must be at least %lu bytes to accomodate this file\n"\
  473.     ,file[0]->size+4+file[1]->size);
  474.     printf("If you require a %lu byte file size use a physical file splitting utility\n",tsize);
  475.   exit(1);
  476.   }
  477. if(!strcmp(saveext,".ZIP") && tsize < file[0]->size+22+fsize2) {
  478.     printf("Error: Impossible to size archive to %lu bytes.\n",tsize);
  479.     printf("%s contains a file, %s, that is %lu bytes compressed.\n",ifile\
  480.     ,file[0]->name,file[0]->size);
  481.     printf("Target file size must be at least %lu bytes to accomodate this file\n"\
  482.     ,file[0]->size+22+fsize2);
  483.   printf("If you require a %lu byte file size use a physical file splitting utility\n",tsize);
  484.   exit(1);
  485.   }
  486. max=0;
  487. /************************* Assign subfiles ****************************/
  488. if(!strcmp(ext,".ARJ"))       for(j=0;j<255;nsize[j++]=file[0]->size+4);
  489. else if(!strcmp(ext,".ZIP"))  for(j=0;j<255;nsize[j++]=22+fsize2);
  490. else if(!strcmp(ext,".LZH"))  for(j=0;j<255;nsize[j++]=1);
  491. for(j=0;j<count;j++) {
  492.     subfile=0;
  493.     while(!file[j]->filenum) {
  494.         if(nsize[subfile]+file[j]->size <= tsize ) {
  495.             nsize[subfile]+=file[j]->size;
  496.             file[j]->filenum = subfile;
  497.             if(subfile>max) max=subfile;
  498.             }
  499.         else {
  500.             subfile++;
  501.             if(subfile>254) puts("Can't create more than 254 subfiles!");
  502.             demand(subfile<=254, Target file size too small - Use a larger target size);
  503.             }
  504.     }
  505. }
  506. /********************* Write Subfiles ***********************************/
  507. if(max<2) {puts("Nothing to do!");exit(0);}
  508. if(argc==4) {
  509.     flags=fnsplit(argv[2],drive,dir,oname,ext); /*assume source name */
  510.     if(!(flags & FILENAME)) strncpy(oname,iname,7);
  511.     fnmerge(prefix,drive,dir,oname,"");
  512.     }
  513. else {
  514. strncpy(oname,iname,7);
  515. fnmerge(prefix,drive,dir,oname,"");   /* No out path, assume source */
  516. }
  517. fp=fopen(ifile,"rb");
  518. demand(fp!=NULL,"Unable to open source file");
  519. for(j=0;j<max;j++) {
  520.     itoa(j+1,suffix,10);
  521.     strcpy(temp,prefix);
  522.     strcat(temp,suffix);
  523.     strcat(temp,saveext);
  524.     sfp=fopen(temp,"rb");
  525.     if(sfp!=NULL) {
  526.         fclose(sfp);
  527.         if(!ovrwrt) {
  528.         do {
  529.           printf("\nFile %s exists, overwrite(Y/N/G)?",temp);
  530.           ans=getche();
  531.             }while(!strchr("YyNnGg", ans));
  532.         puts("\n");
  533.         if(strchr("Gg",ans)) ovrwrt=1;
  534.         if(strchr("Nn",ans)) exit(0);
  535.         }
  536.         demand(!remove(temp), Unable to overwrite file);
  537.         }
  538.     sfp=fopen(temp,"wb");
  539.     demand(sfp!=NULL,Unable to open output file);
  540.     demand(!ferror(sfp),Write error);
  541.     _setcursortype(_NOCURSOR);
  542.     printf("...writing file %s - ",temp);
  543.     for(k=0;k<count;k++) {
  544.         if(file[k]->filenum!=j+1) continue;
  545.         if(k==0 && !strcmp(saveext,".ARJ")) file[0]->filenum++;
  546.         str_len=strlen(file[k]->name);
  547.         clreol();
  548.         printf("%s",file[k]->name);
  549.         while(str_len>0) {
  550.             printf("\b");
  551.             str_len--;
  552.             }
  553.         fseek(fp, file[k]->position, SEEK_SET);
  554.         demand(!ferror(fp), Read error);
  555.         bcount=file[k]->size;
  556.         if(!strcmp(saveext,".ZIP")) {
  557.             bcount-=file[k]->size2;
  558.             file[k]->position=total_size; }
  559.         total_size+=bcount;
  560.         while(bcount) {
  561.         if(bcount>=BUF_SIZ) {
  562.             demand(fread(buffer,1,BUF_SIZ,fp)==BUF_SIZ,Read error);
  563.             demand(fwrite(buffer,1,BUF_SIZ,sfp)==BUF_SIZ,Write error);
  564.             demand(!ferror(sfp),Write error);
  565.             bcount-=BUF_SIZ;
  566.             }
  567.         else {
  568.             demand(fread(buffer,1,bcount,fp)==bcount,Read error);
  569.             demand(fwrite(buffer,1,bcount,sfp)==bcount,Write error);
  570.             demand(!ferror(sfp),Write error)
  571.             bcount=0;
  572.             }
  573.  
  574.             }
  575.         }
  576.         if(!strcmp(saveext,".LZH")) {
  577.             fputc(0,sfp);
  578.             total_size++;
  579.             demand(!ferror(sfp),Write error);
  580.             }
  581.         if(!strcmp(saveext,".ARJ")) {
  582.             fputc(0x60,sfp);
  583.             fputc(0xEA,sfp);
  584.             fputc(0x00,sfp);
  585.             fputc(0x00,sfp);
  586.             total_size+=4;
  587.             demand(!ferror(sfp),Write error);
  588.             }
  589.         if(!strcmp(saveext,".ZIP")) {          /* Write Central ZIP dir */
  590.             count2=0;
  591.             startdir=total_size;
  592.             for(k=0;k<count;k++) {
  593.             if(file[k]->filenum!=j+1) continue;
  594.             fseek(fp, file[k]->position2, SEEK_SET);
  595.             demand(!ferror(fp), Read error);
  596.             demand(fread(buffer,1,42,fp)==42,Read error);
  597.             demand(fwrite(buffer,1,42,sfp)==42,Write error);
  598.             demand(!ferror(sfp),Write error)
  599.             demand(fwrite(&(file[k]->position),sizeof(long),1,sfp)==1,Write error);
  600.             demand(!ferror(sfp),Write error)
  601.             fseek(fp,(long)4,SEEK_CUR);
  602.             demand(fread(buffer,file[k]->size2-46,1,fp)==1,Read error);
  603.             demand(fwrite(buffer,file[k]->size2-46,1,sfp)==1,Write error);
  604.             demand(!ferror(sfp),Write error)
  605.             total_size+=file[k]->size2;
  606.             count2++;
  607.             }
  608.             dirsize=total_size-startdir;
  609.             fseek(fp, fsize, SEEK_SET);                   /* write end of dir */
  610.             demand(!ferror(fp), Read error);
  611.             demand(fread(buffer,1,8,fp)==8,Read error);            /* 8 bytes */
  612.             demand(fwrite(buffer,1,8,sfp)==8,Write error);
  613.             demand(!ferror(sfp),Write error)
  614.             demand(fwrite(&count2,sizeof(int),1,sfp)==1,Write error);
  615.             demand(!ferror(sfp),Write error);
  616.             demand(fwrite(&count2,sizeof(int),1,sfp)==1,Write error);
  617.             demand(!ferror(sfp),Write error);
  618.             demand(fwrite(&dirsize,sizeof(long),1,sfp)==1,Write error);
  619.             demand(!ferror(sfp),Write error);
  620.             demand(fwrite(&startdir,sizeof(long),1,sfp)==1,Write error);
  621.             demand(!ferror(sfp),Write error);
  622.             demand(fwrite(&fsize2,sizeof(int),1,sfp)==1,Write error);
  623.             demand(!ferror(sfp),Write error);
  624.             fseek(fp, (long)14, SEEK_CUR);
  625.             demand(fread(buffer,1,fsize2,fp)==fsize2,Read error);
  626.             demand(fwrite(buffer,1,fsize2,sfp)==fsize2,Write error);
  627.             demand(!ferror(sfp),Write error)
  628.             total_size+=22+fsize2;
  629.         }
  630.  
  631.         fclose(sfp);
  632.         demand(!ferror(sfp),Write error);
  633.         clreol();
  634.         printf("%7lu bytes\n",total_size);
  635.         _setcursortype(_NORMALCURSOR);
  636.         total_size=0;
  637.     }
  638. fclose(fp);
  639. }
  640.  
  641. /****************** SORTFS routine to sort files ***************************/
  642. void sortfs(void) {
  643.     int i,j,k=1;
  644.     record *temp;
  645.     if(!strcmp(saveext,".ARJ")) k=2;
  646.     for(i=k;i<count;i++) {
  647.         j=i;
  648.         temp=file[j];
  649.         while(j>k-1 && file[j-1]->size < temp->size) {
  650.           file[j]=file[j-1];
  651.           j--;
  652.           }
  653.         file[j]=temp;
  654.     }
  655. }
  656. /********************** HELP write help screen ****************************/
  657. void help(void) {
  658. /* Print help screen */
  659. puts("\n\
  660. LSIZE 2.4                  Archive File Sizer                        1-7-94\n\
  661. by Lawrence S. Lewis                                        Willingboro, NJ\n\
  662. \n  This utility program will take an archive file (ZIP/LZH/ARJ) and break it\
  663. \nup into smaller volumes.  You may specify the size of these smaller files.\
  664. \nThis is handy for backing up a large archive to a number of floppy\
  665. \ndiskettes.  The original file is left intact.  Each of the smaller files\
  666. \nwill be readable by the original archive program.  This program will work\
  667. \nwith archives created with LHA.EXE v2.13, ARJ.EXE v2.41, and PKZIP v2.04g. \
  668. \n\nSyntax:   LSIZE   SourceFile   [TargetPrefix]   MaxSize\n\
  669. \n         SourceFile  = name of the archive to be broken up.\
  670. \n       TargetPrefix  = the prefix of the files to be created.\
  671. \n                     = default prefix is source name.\
  672. \n             MaxSize = maximum size(in bytes) of each output file.\
  673. \n                     = also accepts size: 1.44M, 720K, 1.2M, or 360K\
  674. \nExamples:  LSIZE month.lzh day 720K  or  LSIZE month c:\\archive 1.44M\
  675. \n       The first command would split up the file MONTH.LZH into smaller\
  676. \n       files called: DAY1.LZH, DAY2.LZH, DAY3.LZH, DAY4.LZH... Each file\
  677. \n       will be small enough to fit on a 720K floppy disk.");
  678. exit(0);
  679. }